/************************************
 *  Filename: cssp_json.c
 *  Author: zhangwj
 *  Description:
 *  Date: 2017-06-02
 *  Email:
 * **********************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <json-c/json.h>
#include "csssp_common.h"
#include "csssp_json.h"
#include "csssp_mysql.h"

#define CSSP_INFO_TYPE				"InfoType"
#define CSSP_DEV_OWNER				"Owner"
#define CSSP_DEV_NAME				"Device"
#define CSSP_DEV_ADDR				"Address"
#define CSSP_USERNAME				"UserName"
#define CSSP_PASSWORD				"PassWord"
#define CSSP_TERMINAL				"Terminal"
#define CSSP_SENSOR_LIST			"SensorList"
#define CSSP_SENSOR_TYPE			"SensorType"
#define CSSP_SENSOR_DISPLAYNAME		"DisplayName"
#define CSSP_SENSOR_UINT			"QuantityUnit"
#define CSSP_SENSOR_ADDRESS			"Address"
#define CSSP_SENSOR_PLACE			"Place"

#define character_sql				"set names 'utf8';"

#define user_info					"user_info"
#define user_info_sql				"(us_name，us_passwd, us_addr, us_addr, us_date, us_time)"

#define dev_info					"dev_info"
#define dev_info_sql				"(dev_id, dev_name, dev_addr, dev_owner, dev_date, dev_time)"

#define detection_info_list			"detection_info_list"
#define detection_info_sql			"(dt_seq, dt_sub_seq, dt_datetime, dt_usr_name, dt_dev_name, dt_dev_addr, dt_sensor_type, dt_sensor_name, dt_sensor_unit)"


#ifndef is_error
#define is_error(ptr) (ptr == NULL)
#endif

const char *sensor_type[] = {"Temperature", "Humidity", "Noise", "PM2_5", "PM10", "WindDirection", "WindSpeed"};

cssp_sensor_info_t g_sen_info;
cssp_user_info_t g_uinfo;
cssp_dev_info_t g_dinfo;

unsigned int seq_num = 1;
static int cssp_get_seqnum()
{
	return seq_num++;
}

int cssp_json_get_int(struct json_object *json_obj, const char *tag)
{
	int value;
    struct json_object *json_tmp = NULL;
    
    json_object_object_get_ex(json_obj, tag, &json_tmp);
    if (is_error(json_tmp)) {
        CSSP_ERROR("json get tag[%s] error, error[%d:%s]\n", tag, errno, strerror(errno));
        return -1; 
    }   
    value = json_object_get_int(json_tmp);
    CSSP_DEBUG("json %s:%d", tag, value);

    return value;
}

int cssp_json_get_string(struct json_object *json_obj, const char *tag, char *buf)
{
    int len;
	struct json_object *json_tmp = NULL;
    
	json_object_object_get_ex(json_obj, tag, &json_tmp);
    if (is_error(json_tmp)) {
        CSSP_ERROR("json get tag[%s] error, error[%d:%s]\n", tag, errno, strerror(errno));
        return -1; 
    }
   
	len = strlen(json_object_get_string(json_tmp));
    strncpy(buf, json_object_get_string(json_tmp), len);
	buf[len] = '\0';
    CSSP_DEBUG("json %s:%s\n", tag, buf);

    return 0;
}

struct json_object * cssp_string_to_json_object(const char *json)
{
	struct json_object *json_obj = NULL;

	json_obj = json_tokener_parse(json);
	if(is_error(json_obj)) {
		CSSP_ERROR("json parse error, error:[%d:%s]\n", errno, strerror(errno));
		return NULL; 
	}

	return json_obj;
}

struct json_object * cssp_json_get_array_object(struct json_object *json_obj, const char *tag)
{
    struct json_object *json_tmp = NULL;
    
    json_object_object_get_ex(json_obj, tag, &json_tmp);
    if (is_error(json_tmp)) {
        CSSP_ERROR("json get tag[%s] error, error[%d:%s]\n", tag, errno, strerror(errno));
        return NULL; 
    }   

    return json_tmp;
}

int cssp_user_info_handle(struct json_object *json)
{
	char cmd[2048];

	/* get user_name */
	if (cssp_json_get_string(json, CSSP_USERNAME, g_uinfo.user_name)) {
		return -1;
	}

	/* get user_passwd */
	if (cssp_json_get_string(json, CSSP_PASSWORD, g_uinfo.user_passwd)) {
		return -1;
	}
	
	sprintf(cmd, "insert into `%s` %s VALUES ('%s', '%s', '%s', curdate(), curtime());", 
		user_info, user_info_sql, g_uinfo.user_name, g_uinfo.user_passwd, g_uinfo.user_addr);

//	printf("user_info: %s\n", cmd);
		
	return 0;
}

int cssp_device_info_handle(struct json_object *json)
{
	char cmd[2048];

	/* get device name */
	if (cssp_json_get_string(json, CSSP_DEV_NAME, g_dinfo.dev_name)) {
		return -1;
	}

	/* get device owner */
	if (cssp_json_get_string(json, CSSP_DEV_OWNER, g_dinfo.dev_owner)) {
		return -1;
	}

	/* get device addr */
	if (cssp_json_get_string(json, CSSP_DEV_ADDR, g_dinfo.dev_addr)) {
		return -1;
	}

	sprintf(cmd, "insert into `%s` %s VALUES (%d, '%s', '%s', '%s', curdate(), curtime());", 
		dev_info, dev_info_sql, g_dinfo.dev_id, g_dinfo.dev_name, g_dinfo.dev_addr, g_dinfo.dev_owner);

//	printf("dev_info: %s\n", cmd);

	return 0;
}

int cssp_sensor_info_handle(struct json_object *json)
{
	unsigned int slen = 0;
	char cmd[2048];

	/* get sensor type (Humidity or LightIntensity ....)*/
	if (cssp_json_get_string(json, CSSP_SENSOR_TYPE, g_sen_info.sen_type)) {
		return -1;
	}
	
	/* get sensor context */
	if (cssp_json_get_string(json, CSSP_SENSOR_DISPLAYNAME, g_sen_info.sen_context)) {
		return -1;
	}

	/* get sensor context Uint (%....) */
	if (cssp_json_get_string(json, CSSP_SENSOR_UINT, g_sen_info.sen_uint)) {
		return -1;
	}

	slen = sprintf(cmd, "insert into `%s` %s VALUES (%d, %d, now(), '%s', '%s', '%s', '%s', '%s', '%s');",
							detection_info_list, detection_info_sql, g_sen_info.sen_seq, g_sen_info.sen_subseq, 
													g_sen_info.username, g_sen_info.devname, g_sen_info.devaddr, 
													g_sen_info.sen_type, g_sen_info.sen_context, g_sen_info.sen_uint);	
	cssp_mysql_real_insert(cmd, slen);
	return 0;
}

int cssp_sensor_info_list_handle(struct json_object *json)
{
	int i, idx;
	struct json_object *array_json = NULL;
	struct json_object *tmp_json = NULL;

	/* get device name */
	if (cssp_json_get_string(json, CSSP_SENSOR_ADDRESS, g_sen_info.devname)) {
		return -1;
	}

	/* get device addr */
	if (cssp_json_get_string(json, CSSP_SENSOR_PLACE, g_sen_info.devaddr)) {
		return -1;
	}
		
	/* get sensor info of sersor list */
	array_json = cssp_json_get_array_object(json, CSSP_SENSOR_LIST);
	if (NULL == array_json) {
		return -1;
	}

	idx = json_object_array_length(array_json);
	if (idx <= 0) {
		return -1;
	}

	for (i = 0; i < idx; i++) {
		tmp_json = json_object_array_get_idx(array_json, i);
		cssp_sensor_info_handle(tmp_json);
	}
		
	return 0;
}

#if 0
int cssp_terminal_info_list_handle(struct json_object *json)
{
	int i, idx;
	char info_type[12] = {0};
	struct json_object *array_json = NULL;
	struct json_object *tmp_json = NULL;

	if (cssp_json_get_string(json, CSSP_INFO_TYPE, info_type)) {
		return -1;
	}

	if (strcmp(info_type, "Data")) {
		CSSP_DEBUG("Json string Infotype Unkown.......\n");
		return -1;
	}

	/* get device username */
	if (cssp_json_get_string(json, CSSP_USERNAME, g_sen_info.username)) {
		return -1;
	}	

	/*get sensor list of terminal */
	array_json = cssp_json_get_array_object(json, CSSP_TERMINAL);
	if (NULL == array_json) {
		return -1;
	}

	/* get sensor nums */
	g_sen_info.sen_seq = cssp_get_seqnum();
	idx = json_object_array_length(array_json);
	if (idx <= 0) {
		return -1;
	}

	for (i = 0; i < idx; i++) {
		g_sen_info.sen_subseq = i + 1;
		tmp_json = json_object_array_get_idx(array_json, i);
		cssp_sensor_info_list_handle(tmp_json);
	}
	
	return 0;
}
#endif

int cssp_sensors_info_handle(const char *sen_type, const char *sen_data)
{
	int slen;
	char cmd[2048];
	
	slen = sprintf(cmd, "insert into `%s` %s VALUES (%d, %d, now(), '%s', '%s', '%s', '%s', '%s', '%s');",
						detection_info_list, detection_info_sql, g_sen_info.sen_seq, g_sen_info.sen_subseq, 
		g_sen_info.username, g_sen_info.devname, g_sen_info.devaddr, sen_type, sen_data, g_sen_info.sen_uint);	

	cssp_mysql_real_insert(cmd, slen);
	return 0;
}

int cssp_terminal_info_list_handle(struct json_object *json)
{
	int i, len;
	char info_type[12] = {0};
	struct json_object *array_json = NULL;
	struct json_object *tmp_json = NULL;

	if (cssp_json_get_string(json, CSSP_INFO_TYPE, info_type)) {
		return -1;
	}

	if (strcmp(info_type, "Data")) {
		CSSP_DEBUG("Json string Infotype Unkown.......\n");
		return -1;
	}

	if (cssp_json_get_string(json, CSSP_DEV_OWNER, g_sen_info.username)) {
		return -1;
	}
	
	if (cssp_json_get_string(json, CSSP_SENSOR_ADDRESS, g_sen_info.devname)) {
		return -1;
	}

	g_sen_info.sen_subseq = 0;	
	g_sen_info.sen_seq = cssp_get_seqnum();
	len = (sizeof(sensor_type)/sizeof(char *));
	for (i = 0; i < len; i++) {
		if (cssp_json_get_string(json, sensor_type[i], g_sen_info.sen_context)) {
			continue;
		}
		g_sen_info.sen_subseq ++;
		cssp_sensors_info_handle(sensor_type[i], g_sen_info.sen_context);
	}

	return 0;
}

int cssp_data_parse(const char *json, unsigned int len)
{
	struct json_object *json_obj;

	if (NULL == json || len <= 0) {
		return -1;
	}	

	json_obj = cssp_string_to_json_object(json);
	if (json_obj == NULL) {
		return -1;
	}
	CSSP_DEBUG("json_str: %s\n", json_object_to_json_string(json_obj));

	/* transactions starr */
	cssp_mysql_insert(TRANSACTION_START);

#if 0
	/* parse User info */
	cssp_user_info_handle(json_obj);

	/* parse device info */
	cssp_device_info_handle(json_obj);
#endif

	/* parse Terminal info */
	cssp_terminal_info_list_handle(json_obj);
	
	/* transactions commit */
	cssp_mysql_insert(TRANSACTION_END);

	/* release json object */ 
	json_object_put(json_obj);

	return 0;
}

